#include <functional>
#include <vector>
#include "util.hpp"

using func_t = std::function<void()>; // 包装器，包装的可调用对象的返回值是void，参数为空
// using和typedef关键字都是用来声明类型的别名的，using是C++11的用法，推荐使用using来声明类型的别名

#define INIT(v)                  \
    do                           \
    {                            \
        v.push_back(printLog);   \
        v.push_back(download);   \
        v.push_back(executeSql); \
    } while (0);

#define EXEC_OTHER(v)            \
    do                           \
    {                            \
        for (const auto &cb : v) \
        {                        \
            cb();                \
        }                        \
    } while (0);

int main()
{
    std::vector<func_t> cbs;
    INIT(cbs);

    SetNonBlock(0); // 将标准输入设置为非阻塞
    char buffer[1024];
    while (true)
    {
        std::cout << ">>> ";
        fflush(stdout);
        ssize_t s = read(0, buffer, sizeof(buffer) - 1);
        if (s > 0)
        {
            buffer[s] = 0;
            std::cout << "echo# " << buffer;
        }
        else if (s == 0)
        {
            std::cout << "read file end" << std::endl;
            break; // ctrl+d命令行中输入结束，read读到0代表对方输入结束，此时break退出
        }
        else
        {
            // 1.当我不输入的时候，底层0号fd没有数据，算错误吗？ 不算错误！只不过以错误的形式返回了
            // 2.我又如何区分是真的错误，还是仅仅底层没有数据呢？单纯从返回值是无法区分的，但我们可以从设置的错误码errno来区分是底层没有数据 还是 发生了错误
            std::cout << "non-blocking results : " << s << std::endl;
            if (errno == EWOULDBLOCK) // 不要写11 否则就硬编码了
            {
                std::cout << "我没错, 只是底层没有数据" << "errcode: "<< errno << " errstring: "<< strerror(errno)<< std::endl;
                EXEC_OTHER(cbs); // 没有数据等待的时候，让进程做其他的事情
            }
            else if (errno == EINTR)
            {
                std::cout << "The system call was interrupted due to a signal" << std::endl;
            }
            else
            {
                std::cerr << "errno: " << errno << strerror(errno) << std::endl;
                break;
            }
        }

        sleep(1);
    }

    return 0;
}